// Application for subject: Komputerowe Systemy Rozpoznawania
// Authors: Łukasz Kucharczyk, Adam Taciak
// Łódź, 2.10.2012

package app;

import java.io.EOFException;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

import alphas.NGramAlpha;

import classifier.FileReader;
import classifier.NearestNeighborAlgorithm;
import classifier.NearestNeighborAlgorithm.metric_t;
import extractors.BagOfWords;
import extractors.Extractor;
import extractors.OurExtractor;
import extractors.SimilarityMeasure;
import extractors.TermFrequencyMatrix;
import extractors.TriGram;

import parser.ArticleParser;
import parser.FileParser;
import parser.ReuterParser;
import primitive.Article;
import primitive.Pair;


public class Application {
	enum ApplicationMode { FILE_PARSING, EXTRACTION, CLASSIFICATION };
	enum ExtractionMode { SIMILARITY, EXTRACTOR };
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		System.out.println("Start of application at " + new Date());
		
		ApplicationMode mode = ApplicationMode.CLASSIFICATION;
		
		Extractor extractor;
		SimilarityMeasure similarity;
		FileReader reader;
		
		String raw_articles_dir = "files/reuters21578/";
		String xml_training_file = "files/training_set.xml";
		String xml_testing_file = "files/testing_set.xml";
		
		String extracted_features_file = "files/features.txt";
		
		List<Pair> labels = new ArrayList<>();
		//labels.add(new Pair("places", "usa"));
		//labels.add(new Pair("places", "uk"));
		//labels.add(new Pair("places", "japan"));
		//labels.add(new Pair("places", "canada"));
		//labels.add(new Pair("places", "west-germany"));
		//labels.add(new Pair("places", "france"));
		labels.add(new Pair("people", "sumita"));
		labels.add(new Pair("people", "maxwell"));
		labels.add(new Pair("people", "young"));
		labels.add(new Pair("people", "thatcher"));
		labels.add(new Pair("people", "miyazawa"));
		
		
		switch (mode) {
		case FILE_PARSING:
			System.out.println("Parsing reuters files...");
			
			ArrayList<String> labels_to_save = new ArrayList<>();
			labels_to_save.add("people");
			labels_to_save.add("places");
			labels_to_save.add("body");
			labels_to_save.add("title");
			

			ReuterParser rp = new ReuterParser();
			rp.setSgmDirectory(raw_articles_dir);
			rp.setTestingFileName(xml_testing_file);
			rp.setTrainingFileName(xml_training_file);
			rp.setTrainingRatio(0.6);
			rp.setLabels(labels_to_save);
			rp.run();
			
			break;
		case EXTRACTION:
			System.out.println("Features extraction...");
			// Read all extracted articles from training file
			reader = new FileReader();
			reader.run(xml_training_file);
			
			List<Article> extraction_articles;
			extraction_articles = reader.get_articles();
			
			extractor = new OurExtractor();
			extractor.set_labels(labels);
			extractor.featuresExtraction(extraction_articles);
			extractor.featuresSave(extracted_features_file);
			
			break;
		case CLASSIFICATION:
			
			reader = new FileReader();
			reader.run(xml_testing_file);
			
			List<Article> testing_articles;				// Needed by kNN
			testing_articles = reader.get_articles();	// Needed by kNN
			
			
			reader = new FileReader();
			reader.run(xml_training_file);				// Needed by similarity
			List<Article> training_articles;			// Needed by similarity
			training_articles = reader.get_articles();	// Needed by similarity
						
			extractor = new OurExtractor();
			extractor.set_labels(labels);
			extractor.loadFeatures(extracted_features_file);
			extractor.getTrainingSet();
			
			similarity = new TriGram();
			similarity.setTrainingData(training_articles);	// Insert training data to similarity object (its gonna be taken in kNN)
			
			//List<HashMap<String, List<Double>>> training_set = extractor.getTrainingSet();
			
			NearestNeighborAlgorithm knn = new NearestNeighborAlgorithm();
			knn.init(5);
			knn.set_active_metric(metric_t.EUCLIDEAN);
			knn.setExtractor(extractor);
			//knn.setSimilarityMeasure(similarity);
			//knn.set_training_vectors(training_set);		// deprecated, functionality has been moved to knn object
			//knn.set_testing_vectors(vectors);				// deprecated, new functionality does not use it
			knn.set_testing_data(testing_articles);
			
			System.out.println(training_articles.size() + " " + testing_articles.size());
			
			knn.run();
			knn.show_results();
			
			break;
		}

		
		
	
		//-------------------------------------------------------------
		
		
		//parser.drop_useless_articles();
		//parser.save_articles(xml_articles_file, labels_to_save);
		
		// Second part of application, computations
		List<Article> articles_list;
		

		
//		FileReader file_reader = new FileReader();
//		file_reader.run(xml_articles_file);
//		articles_list = file_reader.get_articles();
		
//		ArticleParser p = new ArticleParser();
//		p.remove_all(articles_list.get(1)).show();
//		
//		articles_list.get(1).show();
		
//		OurExtractor our = new OurExtractor();
//		our.set_labels(labels);
//		our.set_articles(articles_list);
//		our.run();
		
//		List<HashMap<String, List<Double>>> fv = our.get_vectors();
		
		// preview
		//for (int i = 0; i < fv.size(); ++i) {
		//	System.out.println(fv.get(i));
		//}
		
		
		// Extractors...
//		BagOfWords bag = new BagOfWords();
//		bag.set_articles(articles_list);		// Put input data
//		bag.set_labels(labels);					// Put labels, according to follow pattern: label = value
//		bag.run();								// Execute computation
//		fv = bag.get_vectors();						// Get results
		
		
		//for (int i = 0; i < fv.size(); ++i) {
		//	System.out.println(fv.get(i).keySet().iterator().next());
		//}
		
		
		List<HashMap<String, List<Double>>> training = new ArrayList<>();
		List<HashMap<String, List<Double>>> testing = new ArrayList<>();
		
//		int training_below = (int) ((double)fv.size() * 0.4);
		
		// Split feature vector
//		for (int i = 0; i < fv.size(); ++i) {
//			if (i < training_below) {
//				training.add(fv.get(i));
//			} else {
//				testing.add(fv.get(i));
//			}
//		}
		
		
		/*
		TermFrequencyMatrix freq = new TermFrequencyMatrix();
		freq.set_labels(labels);
		freq.set_articles(articles_list);
		freq.run();
		freq.get_vectors();
		*/
		
		/*
		// Generate experimental vectors
		List<HashMap<String, List<Double>>> training = new ArrayList<>();
		List<HashMap<String, List<Double>>> testing = new ArrayList<>();
		
		Random random = new Random();
		random.nextInt(labels.size());
		
		// Training
		for (int i = 0; i < 1000; ++i) {
			String category = labels.get(random.nextInt(labels.size())).second;
			List<Double> vec = new ArrayList<>();
			for (int j = 0; j < 15; ++j) {
				vec.add(random.nextDouble());
			}
			
			// Append to main vector
			HashMap<String, List<Double>> pos = new HashMap<>();
			pos.put(category, vec);
			training.add(pos);
		}
		
		// Testing
		for (int i = 0; i < 4000; ++i) {
			String category = labels.get(random.nextInt(labels.size())).second;
			List<Double> vec = new ArrayList<>();
			for (int j = 0; j < 15; ++j) {
				vec.add(random.nextDouble());
			}
			
			// Append to main vector
			HashMap<String, List<Double>> pos = new HashMap<>();
			pos.put(category, vec);
			testing.add(pos);
		}
		*/
		
		
		{
		// Testing only..... KNN
			/*
		NearestNeighborAlgorithm knn = new NearestNeighborAlgorithm();
		knn.set_active_metric(metric_t.EUCLIDEAN);
		knn.set_training_vectors(training);
		knn.set_testing_vectors(testing);
		
		knn.run();
		knn.show_results();*/
		}
		
				
		
		System.out.println("Stop of application at " + new Date());
	}

}
